package com.hua.designpattern.structural.proxy;

import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;

/**
 * 
 * @author joshua
 *
 *         <pre>
 *
 *  在代理模式（Proxy Pattern）中，一个类代表另一个类的功能。在代理模式中，创建具有现有对象的对象，以便向外界提供功能接口。
 *
 *  优点： 1、职责清晰。 2、高扩展性。 3、智能化。
 *  缺点：  1、由于在客户端和真实主题之间增加了代理对象，因此有些类型的代理模式可能会造成请求的处理速度变慢。 
 *       2、实现代理模式需要额外的工作，有些代理模式的实现非常复杂。
 *
 *
 *    和适配器模式的区别：适配器模式主要改变所考虑对象的接口，而代理模式不能改变所代理类的接口。
 *    和装饰器模式的区别：装饰器模式为了增强功能，而代理模式是为了加以控制。
 * 
 *     REF:
 *        远程代理。
 *        虚拟代理。
 *        AspectJ
 *        spring AOP
 * 
 *         </pre>
 *
 *
 */

public class TestProxy {

	public static void main(String[] args) {
		// 简单代理
		GameInterface gameCommon = new GameProxy(new GameConcrete());
		gameCommon.login("player");
		gameCommon.playGame();
		gameCommon.logout("player");

		// 反向代理(强制代理)
		System.out.println("----不能直接访问原对象----");
		GameInterface gameConcreteReverse1 = new GameConcreteReverse();
		gameConcreteReverse1.login("player");
		gameConcreteReverse1.playGame();
		gameConcreteReverse1.logout("player");
		System.out.println("----不能直接访问代理对象----");
		GameInterface gameConcreteReverse2 = new GameProxy(new GameConcreteReverse());
		gameConcreteReverse2.login("player");
		gameConcreteReverse2.playGame();
		gameConcreteReverse2.logout("player");

		System.out.println("----只能访问通过原对象返回的代理对象----");
		GameConcreteReverse gameConcreteReverse3 = new GameConcreteReverse();
		GameInterface gameProxyFromConcrete = gameConcreteReverse3.getProxy();
		gameProxyFromConcrete.login("player");
		gameProxyFromConcrete.playGame();
		gameProxyFromConcrete.logout("player");

		// 动态代理：jdk动态代理是由Java内部的反射机制来实现的，cglib动态代理底层则是借助asm来实现的。
		System.out.println("----接口实现动态代理(jdk动态代理)----");
		GameInterface target = new GameConcrete();
		DynamicProxyInvocationHandler dynamicProxy = new DynamicProxyInvocationHandler(target);
		GameInterface gameProxyJDK = (GameInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(),
				new Class[] { GameInterface.class }, dynamicProxy);
		gameProxyJDK.login("player");
		gameProxyJDK.playGame();
		gameProxyJDK.logout("player");

		System.out.println("----编译字节码实现动态代理(cglib动态代理)----");
		DynamicProxyMethodInterceptor cglibProxy = new DynamicProxyMethodInterceptor();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(GameConcrete.class);
		enhancer.setCallback(cglibProxy);

		GameConcrete gameProxyCglib = (GameConcrete) enhancer.create();
		gameProxyCglib.login("player");
		gameProxyCglib.playGame();
		gameProxyCglib.logout("player");

	}

}
